/*
 * @Description:
 * @Version:
 * @Author: Troubadour
 * @Date: 2022-09-10 10:41:13
 * @LastEditors: Troubadour
 * @LastEditTime: 2022-09-12 12:43:48
 */

#include "infrared.h"

extern uint8_t Ctrl_Display;

/**
 * @function: Infrared_Manage
 * @brief: 处理红外遥控器键值
 * @param {const uint32_t} *Infrared_value：键值
 * @return {*}
 */
void Infrared_Manage(const uint32_t *Infrared_value)
{
    static uint8_t NowServo = 1;
    switch (*Infrared_value)
    {
    case Infrared_Up:
        if(DEBUG_PRINTF) printf("Value: 0x%08X , Infrared_Up\r\n", *Infrared_value);
        ServoAll[NowServo].pwm += 50;
        Control_Servo_OnlyOne(ServoCmd, &ServoAll[NowServo]);
        // // HAL_UART_Transmit(&huart2, ServoCmd, strlen((char *)ServoCmd), 100);
        DMA_ServoSendData(ServoCmd, strlen((char *)ServoCmd));
        if(DEBUG_PRINTF) printf("Cmd: %s\r\n", ServoCmd);
        break;

    case Infrared_Down:
        if(DEBUG_PRINTF) printf("Value: 0x%08X , Infrared_Down\r\n", *Infrared_value);
        ServoAll[NowServo].pwm -= 50;
        Control_Servo_OnlyOne(ServoCmd, &ServoAll[NowServo]);
        // HAL_UART_Transmit(&huart2, ServoCmd, strlen((char *)ServoCmd), 100);
        DMA_ServoSendData(ServoCmd, strlen((char *)ServoCmd));
        if(DEBUG_PRINTF) printf("Cmd: %s\r\n", ServoCmd);
        break;

    case Infrared_Left:
        if(DEBUG_PRINTF) printf("Value: 0x%08X , Infrared_Left\r\n", *Infrared_value);
        ServoAll[0].pwm -= 50;
        Control_Servo_OnlyOne(ServoCmd, &ServoAll[0]);
        // HAL_UART_Transmit(&huart2, ServoCmd, strlen((char *)ServoCmd), 100);
        DMA_ServoSendData(ServoCmd, strlen((char *)ServoCmd));
        if(DEBUG_PRINTF) printf("Cmd: %s\r\n", ServoCmd);
        break;

    case Infrared_Right:
        if(DEBUG_PRINTF) printf("Value: 0x%08X , Infrared_Right\r\n", *Infrared_value);
        ServoAll[0].pwm += 50;
        Control_Servo_OnlyOne(ServoCmd, &ServoAll[0]);
        // HAL_UART_Transmit(&huart2, ServoCmd, strlen((char *)ServoCmd), 100);
        DMA_ServoSendData(ServoCmd, strlen((char *)ServoCmd));
        if(DEBUG_PRINTF) printf("Cmd: %s\r\n", ServoCmd);
        break;

    case Infrared_Ok:
        if(DEBUG_PRINTF) printf("Value: 0x%08X , Infrared_Ok\r\n", *Infrared_value);
        Control_ServoReset(ServoCmd);
        // HAL_UART_Transmit(&huart2, ServoCmd, strlen((char *)ServoCmd), 100);
        DMA_ServoSendData(ServoCmd, strlen((char *)ServoCmd));
        break;

    case Infrared_T1:
        if(DEBUG_PRINTF) printf("Value: 0x%08X , Set PULK!\r\n", *Infrared_value);
        Control_Servo_ALLPULR(ServoCmd, 0);
        DMA_ServoSendData(ServoCmd, strlen((char *)ServoCmd));
        break;

    case Infrared_T2:
        if(DEBUG_PRINTF) printf("Value: 0x%08X , Set PULR!\r\n", *Infrared_value);
        Control_Servo_ALLPULR(ServoCmd, 1);
        DMA_ServoSendData(ServoCmd, strlen((char *)ServoCmd));
        break;

    case Infrared_Key0:
        if(DEBUG_PRINTF) printf("Value: 0x%08X , Set display\r\n", *Infrared_value);
        if(Ctrl_Display) Ctrl_Display = 0;
        else Ctrl_Display = 1;
        break;

    case Infrared_Key1:
        if(DEBUG_PRINTF) printf("Value: 0x%08X , Control 1 Servo\r\n", *Infrared_value);
        NowServo = 1;
        break;

    case Infrared_Key2:
        if(DEBUG_PRINTF) printf("Value: 0x%08X , Control 2 Servo\r\n", *Infrared_value);
        NowServo = 2;
        break;

    case Infrared_Key3:
        if(DEBUG_PRINTF) printf("Value: 0x%08X , Control 3 Servo\r\n", *Infrared_value);
        NowServo = 3;
        break;

    case Infrared_Key4:
        if(DEBUG_PRINTF) printf("Value: 0x%08X , Control 4 Servo\r\n", *Infrared_value);
        NowServo = 4;
        break;

    case Infrared_Key5:
        if(DEBUG_PRINTF) printf("Value: 0x%08X , Control 5 Servo\r\n", *Infrared_value);
        NowServo = 5;
        break;

    default:
        if(DEBUG_PRINTF) printf("Value: 0x%08X , Not Function\r\n", *Infrared_value);
        break;
    }
}


/**
 * @function: Read_Infrared
 * @brief 根据给定引脚，接收一次红外遥控器的值，长按时返回之前的值。经仅支持NEC协议
 * @param {GPIO_TypeDef} *GPIOx：接了红外遥控器的引脚端口
 * @param {uint16_t} GPIO_Pin：接了红外遥控器的引脚号
 * @param {uint32_t} *data：接收红外数据
 * @return {HAL_StatusTypeDef} HAL_OK：接收正常，HAL_ERROR：接收失败
 */
HAL_StatusTypeDef Read_Infrared(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, uint32_t *data)
{
    uint8_t i = 0, j = 0;
    uint16_t count = 0;
    uint8_t RawData[4] = {0};
    static uint32_t lastData = 0;

    Delay_ms_Func(8);
    if(ReadPin(GPIOx, GPIO_Pin) != 0)
    {
        return HAL_ERROR;
    }

    count = 0;
    while(ReadPin(GPIOx, GPIO_Pin) == 0)    // 等待9ms的低电平，超时退出
    {
        Delay_us_Func(1);
        if(count++ > 2000)
        {
            return HAL_ERROR;
        }
    }

    Delay_ms_Func(4);                       // 等待4.5ms的高电平的4ms
    if(ReadPin(GPIOx, GPIO_Pin) != 1)
    {
        return HAL_ERROR;
    }

    count = 0;
    while(ReadPin(GPIOx, GPIO_Pin) == 1)    // 等待4.5ms剩下的的高电平，超时退出
    {
        Delay_us_Func(1);
        if(count++ > 1000)
        {
            break;
        }
    }

    for(i=0; i<4; i++)      // 接收4字节数据
    {
        for(j=0; j<8; j++)
        {
            count = 60;
            while ((ReadPin(GPIOx, GPIO_Pin) == 0) && (count-- > 0))    // 等待每个字节前的560us低电平
            {
                Delay_us_Func(10);
            }

            count = 0;
            while (ReadPin(GPIOx, GPIO_Pin) == 1)   // 判断高电平时间
            {
                Delay_us_Func(100);
                count++;
                if(count > 20)      // 长按检测
                {
                    break;
                }
            }

            RawData[i] >>= 1;
            if(count >= 11)           // 高电平数据,1.68ms(1.2ms~2.0ms),低电平数据,0.56ms(0.2ms~1ms)
            {
                RawData[i] |= 0x80;
            }
        }
    }
    *data = (uint32_t)(RawData[0]<<24 | RawData[1]<<16 | RawData[2]<<8 | RawData[3]);
    // 长按时返回之前的值
    if(*data == 0xFFFFFFFF)
    {
        *data = lastData;
    }
    else
    {
        lastData = *data;
    }
    Infrared_Manage((const uint32_t *)data);    // 处理键值
    return HAL_OK;
}
